サブ要素をループするAnsibleのwith_subelements
渡辺です。
AnsibleのPlaybookやRoleの再利用性を高めるためには、綺麗なグループ変数定義を目標とし、タスク定義でゴニョゴニョするのが基本です。 今回は、こんなグループ変数に役立つwith_subelementsを紹介します。
vars: users: - name: user1 groups: - wheel - hoge - name: user2 groups: - hoge
要は多重ループをしたいってことになります。 プログラミング的にはこんなイメージです(擬似コード)。
for (user in users) { for (group in user.groups) { # user と groupによる処理 } }
with_subelementsによる多重ループ
結論から言えば、with_subelements
を利用することで多重ループを処理することができます。
ただ、微妙に解りにくいシンタックスなので、注意が必要です。
tasks: - debug: msg: "name={{ item.0.name }}, group={{ item.1 }}" with_subelements: - "{{ users }}" - groups
with_subelements
にはリストでループする要素を指定します。
ひとつめ目の要素には、ループの主体となる要素、すなわちusers
を指定します。
ここまでは通常のwith_items
と同様です。
ふたつ目の要素には、ループの主体となる要素から多重ループさせたい要素名を指定します。
要素名ですから、変数の内部展開("{{ groups }}"
)と記述しないことに注意してください。
モジュールで要素を参照する時はitem
という予約された変数名を使う点は、with_items
と同様です。
ですが、はじめにitem.0
やitem.1
のように、with_subelements
で指定した要素のインデックスを指定します。
item.0
はusers
の各要素になるため、name
を参照するならば、item.0.name
となります。
item.1
はgroups
の各要素なのでそのまま利用すれば良いでしょう。
出力結果は次のようになります。
TASK [debug] ******************************************************************* ok: [localhost] => (item=({u'name': u'user1'}, u'wheel')) => { "item": [ { "name": "user1" }, "wheel" ], "msg": "name=user1, group=wheel" } ok: [localhost] => (item=({u'name': u'user1'}, u'hoge')) => { "item": [ { "name": "user1" }, "hoge" ], "msg": "name=user1, group=hoge" } ok: [localhost] => (item=({u'name': u'user2'}, u'hoge')) => { "item": [ { "name": "user2" }, "hoge" ], "msg": "name=user2, group=hoge" }
期待通りにループできていることが解ると思います。
一部の要素がない場合はskip_missingを利用する
グループ変数が、次のように一部のネスト変数を持たない場合、多重ループはエラーとなります。
vars: users: - name: user1 groups: - wheel - hoge - name: user2 groups: - hoge - name: user3
このような場合は、3つ目の要素flags
を追加し、ディクショナリにskip_missing
をTrue
に設定することで、ループをスキップすることが可能です。
tasks: - debug: msg: "name={{ item.0.name }}, group={{ item.1 }}" with_subelements: - "{{ users }}" - groups - flags: skip_missing: True
まとめ
グループ変数に定義したリストが更にリストを持つパターンは多いと思います。
with_items
に加えて、with_subelements
を道具箱に入れておけば、Ansibleをより効率良く使えるようになるでしょう。
なお、3重以上のループには対応していません。